#ifndef A8_REDIS_HPP
#define A8_REDIS_HPP

#include <a8/xvalue.hpp>
#include <hiredis.h>

namespace a8
{
	static a8::XValue RedisReplyToXValue(redisReply* reply)
	{
		if(reply){
			switch(reply->type){
			case REDIS_REPLY_STRING:
				{
					a8::XValue val;
					val.SetDynData(reply->str, reply->len);
					return val;
				}
				break;
			case REDIS_REPLY_INTEGER:
				{
					return a8::XValue(reply->integer);
				}
				break;
			case REDIS_REPLY_NIL:
				{
					a8::XValue val;
					val.Set("");
					return val;
				}
				break;
			case REDIS_REPLY_ARRAY:
				{
					a8::XValue val;
					val.SetUserData(reply->element, reply->elements);
					return val;
				}
				break;
			default:
				return a8::XValue();
			}
		}else{
			return a8::XValue();
		}
	}

	class Redis
	{
	public:

		Redis(const std::string& host, int port, int timeout=10)
		{
			mHost = host;
			mPort = port;
			mTimeOut = timeout;
			mRedis = NULL;
		}

		~Redis()
		{
			if(mRedis){
				redisFree(mRedis);
				mRedis = NULL;
			}
		}

		bool Connect()
		{
			//mRedis = redisConnectWithTimeOut(mHost.c_str(), mPort, mTimeOut);
			return mRedis && !mRedis->err;
		}

		bool Ping()
		{
			ExecCommand("PING");
			return true;
		}
		
		a8::XValue ExecCommand(const std::string& command)
		{
			redisReply *reply = (redisReply*)redisCommand(mRedis, command.c_str());
			return RedisReplyToXValue(reply);
		}

	private:
		redisContext *mRedis;
		std::string mHost;
		int mPort;
		int mTimeOut;
	};

}

#endif
